package cn.com.dhcc.turbo.dao.registry;

import java.util.ArrayList;
import java.util.List;

import org.apache.log4j.Logger;
import org.springframework.stereotype.Repository;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

import cn.com.dhcc.app.core.CM;
import cn.com.dhcc.app.core.dao.AbstractCrudDao;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.handler.modulehandler.WhereCondition;
import cn.com.dhcc.app.core.handler.modulehandler.valuebean.LikeValue;
import cn.com.dhcc.app.core.handler.pagerhandler.Pager;
import cn.com.dhcc.app.core.handler.pagerhandler.PagerData;
import cn.com.dhcc.app.core.service.Log;
import cn.com.dhcc.app.core.service.Log.LOGTYPE;
import cn.com.dhcc.app.core.tag.CommonStaticCode.YESNO;
import cn.com.dhcc.app.pub.core.consts.NodeInfoParam;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.entity.registry.wapper.NodeInfoRowWapper;

/**
 * 
 * 
 * @日期：2014-5-12 上午11:36:45
 * @作者：张洪涛
 * @版权所有：东华软件
 * @版本：1.0
 */
@Repository
public class NodeInfoDao extends AbstractCrudDao<NodeInfo> {
	@SuppressWarnings("deprecation")
	private static Logger logger = Log.getExistLogger(LOGTYPE.TURBO);

	/**
	 * 通过根节点行政行区代码获取根节点
	 * @param rootOrg
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getNodeInfoByNodeCode(String rootOrg) throws DaoException {
		try {
			String netType=NodeInfoParam.NODE_NET_TYPE;
			String sql = "select * from " + SI_TABLE("turbo_node_info")
					+ " where subStr(node_code, 0, 6) ='" + rootOrg + "' and net_type=?";
			return CM.getDao().getModule("根据rootOrg获取Node", sql,
					NodeInfo.class, new Object[]{netType});
		} catch (DaoException e) {
			logger.error("获取节点信息列表失败", e);
			throw new DaoException("获取节点信息列表失败", e);
		}
	}
	/**
	 * 通过根节点行政行区代码获取根节点
	 * @param pid
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getNodeInfoByPid(String pid) throws DaoException {
		try {
			String netType=NodeInfoParam.NODE_NET_TYPE;
			String sql = "select * from " + SI_TABLE("turbo_node_info")
					+ " where pid=? and net_type=?";
			return CM.getDao().getModule("根据rootOrg获取Node", sql,
					NodeInfo.class, new Object[]{pid,netType});
		} catch (DaoException e) {
			logger.error("获取节点信息列表失败", e);
			throw new DaoException("获取节点信息列表失败", e);
		}
	}
	public NodeInfo getRootNodeInfoByNodeCode(String rootOrg,String netType) throws DaoException {
		try {
			String sql = "select * from " + SI_TABLE("turbo_node_info")
					+ " where subStr(node_code, 0, 6) ='" + rootOrg + "' and net_type=? and status='1'";
			return CM.getDao().getModule("根据rootOrg获取Node", sql,
					NodeInfo.class, new Object[]{netType});
		} catch (DaoException e) {
			logger.error("获取节点信息列表失败", e);
			throw new DaoException("获取节点信息列表失败", e);
		}
	}
	/**
	 * 节点信息列表
	 * 
	 * @return
	 * @throws ServiceException
	 */
	public PagerData<NodeInfo> list(Pager pager, WhereCondition condition)
			throws DaoException {
		String msg = "";
		String sql = "select * from " + SI_TABLE("turbo_node_info");
		try {
			return CM.getDao().getPagerList("获取节点信息列表", sql,
					new NodeInfoRowWapper(), pager, condition, new Object[] {});
		} catch (DaoException e) {
			msg = "获取节点信息列表失败";
			logger.error("获取节点信息列表失败", e);
			throw new DaoException(msg, e);
		}
	}

	public int getMaxNodeCode(String str) throws DaoException {
		try {
			final String sql = "select max(subStr(node_code,8)) "
				    +"from "+ SI_TABLE("turbo_node_info")+" where subStr(node_code,0,7)=? ";
			int maxCode =(CM.getDao().queryForInt("获取最大节点编码", sql, new Object[]{str}) != null ? CM.getDao().queryForInt("获取最大节点编码", sql, new Object[]{str}):0)+1;
			return maxCode;
		} catch (DaoException e) {
			throw new DaoException("获取最大节点编码失败！", e);
		}
	}

	/**
	 * 验证节点名称唯一性
	 * 
	 * @param name
	 * @param checkStr
	 * @return
	 * @throws DaoException
	 */
	public boolean checkNodeName(String name, String checkStr)
			throws DaoException {
		try {
			final String sql = "select count(*) from "
					+ SI_TABLE("turbo_node_info")
					+ " where node_code like ?||'%' and node_name=? and status=1";
			return CM.getDao().queryForInt("验证节点名称唯一性", sql,
					new Object[] { checkStr, name }) > 0;
		} catch (DaoException e) {
			throw new DaoException("验证节点名称唯一性失败！", e);
		}
	}

	/**
	 * 批量删除
	 * 
	 * @param ids
	 * @return
	 * @throws DaoException
	 * @throws IllegalArgumentException
	 */
	public int batchDelete(String[] ids) throws DaoException,
			IllegalArgumentException {
		int num = 0;
		try {
			Assert.noNullElements(ids);
			List<Object[]> params = new ArrayList<Object[]>();
			for (String id : ids) {
				params.add(new Object[] { id });
			}
			String sql = "update  " + SI_TABLE("turbo_node_info")
					+ " set  status='0',mtime=sysdate where id = ?";
			num = CM.getDao().batchUpdate("批量删除", sql, params);
		} catch (DaoException e) {
			throw new DaoException("批量删除失败", e);
		}
		return num;
	}

	/**
	 * 通过pid获取子节点
	 * 
	 * @param pid父节点id
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getAllList(String pid) throws DaoException {
		try {
			final String sql = "select t1.id,t1.node_name,t1.pid, t1.node_code,t1.islocal,t1.net_type,count(t2.id) cont"
					+ "   from turbo_node_info t1"
					+ "   left join turbo_node_info t2"
					+ "   on t1.id = t2.pid"
					+ "     where t1.pid = ? and  t1.status ='1' "
					+ "    group by t1.id, t1.node_name,t1.pid,t1.node_code,t1.islocal,t1.net_type "
					+ "	 order by t1.node_code";
			return CM.getDao().list("获取子节点", sql, new NodeInfoRowWapper(),
					new Object[] { pid });
		} catch (DaoException e) {
			throw new DaoException("获取子节点失败！", e);
		}
	}

	/**
	 * 获取全部有效节点，按节点类型排序
	 * 
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getAllNodeList() throws DaoException {
		try {
			final String sql = "select * from "
					+ SI_TABLE("turbo_node_info")
					+ " where  status <>'0' order by islocal desc,node_code asc";
			return CM.getDao().list("获取全部子节点", sql, new NodeInfoRowWapper(),
					new Object[] {});
		} catch (DaoException e) {
			throw new DaoException("获取全部子节点失败！", e);
		}
	}

	/**
	 * 获取Root节点
	 * 
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getRootNodeInfo() throws DaoException {
		try {
			String netType = NodeInfoParam.NODE_NET_TYPE;
			String mwrPid= NodeInfoParam.MWR_NODE_PID;
			final String sql = "select *  from "
					+ SI_TABLE("turbo_node_info")
					+ " where pid=? and status <>'0' and net_type=?";
			return CM.getDao().get("获取Root节点信息", sql, new NodeInfoRowWapper(),
					new Object[] {mwrPid,netType});
		} catch (DaoException e) {
			throw new DaoException("获取Root节点失败！", e);
		}
	}

	/**
	 * 获取本地节点
	 * 
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getLocalNode() throws DaoException {
		try {
			String netType = NodeInfoParam.NODE_NET_TYPE;
			final String sql = "select *  from " + SI_TABLE("turbo_node_info") + " where islocal='1' and net_type=?";
			return CM.getDao().get("获取本地节点信息", sql, new NodeInfoRowWapper(), new Object[] {netType});
		} catch (DaoException e) {
			throw new DaoException("获取本地节点失败！", e);
		}
	}
	/**
	 * 获取本地节点,不区分网络类型
	 * 
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getLocalNodeNoNetType() throws DaoException {
		try {
			final String sql = "select *  from " + SI_TABLE("turbo_node_info") + " where islocal='1'";
			return CM.getDao().get("获取本地节点信息", sql, new NodeInfoRowWapper(), new Object[] {});
		} catch (DaoException e) {
			throw new DaoException("获取本地节点失败！", e);
		}
	}

	/**
	 * 获取有交换关系的节点个数
	 * 
	 * @return
	 * @throws DaoException
	 */
	public int getRelNodeNum() throws DaoException {
		try {
			final String sql = "select count(*) from "
					+ SI_TABLE("TURBO_EXCH_REL");
			return CM.getDao()
					.queryForInt("获取有交换关系的节点个数", sql, new Object[] {});
		} catch (DaoException e) {
			throw e;
		}
	}

	/**
	 * 验证编码是否已经被远程节点占用
	 * 
	 * @param nodeCode
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo ifNodeCodeIsUesedByNotLocalNode(String nodeCode)
			throws DaoException {
		String sql = "select node_name from  " + SI_TABLE("turbo_node_info")
				+ " t where t.islocal<>'" + YESNO.YES.getStatus()
				+ "' and node_code=?";
		try {
			return CM.getDao().getModule("验证编码是否已经被远程节点占用", sql,
					NodeInfo.class, new Object[] { nodeCode });
		} catch (DaoException e) {
			throw e;
		}
	}

	@SuppressWarnings("rawtypes")
	public boolean isPropertyUnique(String property, String newValue,
			String oldValue, String orgCode) throws DaoException {
		if (newValue.equals(oldValue)) {
			return true;
		}
		String whereSQL = "";
		if (NodeInfoParam.MWR_NODEREGION_CODE.equals(orgCode)) {// 水利部
			whereSQL = "__0000";
		} else if (orgCode.equals("110000") || orgCode.equals("120000")
				|| orgCode.equals("310000") || orgCode.equals("500000")) {
			whereSQL = orgCode.substring(0, 2) + "____";
		} else if ("0000".equals(orgCode.substring(2, 6))) {// 省，自治区、流域
			whereSQL = orgCode.substring(0, 2) + "__00";
		} else if ("00".equals(orgCode.substring(4, 6))) {// 市
			whereSQL = orgCode.substring(0, 4) + "__ ";
		}
		final String sql = "select * from " + SI_TABLE("turbo_node_info")
				+ " where node_code like ?||'%' and " + property
				+ "=? and status=1";
		try {
			List list = CM.getDao().list("验证唯一", sql, new NodeInfoRowWapper(),
					new Object[] { whereSQL, newValue });
			if (list.size() == 0)
				return true;
		} catch (DaoException e) {
			throw new DaoException("验证唯一失败！", e);
		}
		return false;
	}

	/**
	 * 获取与节点进行数据交换的全部子节点列表 包含有关系节点和管理范围内的节点
	 * 
	 * @param nodeId
	 *            当前节点ID
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getAllExchNodeList(String nodeId) throws DaoException {
		try {
			final String sql = "select distinct t2.*"
					+ " from "
					+ SI_TABLE("turbo_exch_rel")
					+ " t1, "
					+ SI_TABLE("turbo_node_info")
					+ " t2"
					+ "	 where (t1.node_id_creator = t2.id or t1.node_id_to = t2.id)"
					+ "	   and (t1.node_id_creator = ?"
					+ "	    or t1.node_id_to = ? or t2.pid=?)";
			return CM.getDao().list("获取与本节点进行数据交换的节点列表", sql,
					new NodeInfoRowWapper(),
					new Object[] { nodeId, nodeId, nodeId });
		} catch (DaoException e) {
			throw new DaoException("获取与本节点进行数据交换的节点列表失败！", e);
		}
	}
	/**
	 * 获取节点进行数据交换的节点列表
	 * @param nodeId
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getAllLocalExchNodeList(String nodeId) throws DaoException {
		try {
			final String sql = "select distinct t2.id,t2.node_name,count(t3.id) cont"
					+ " from "
					+ SI_TABLE("turbo_exch_rel")+ " t1, "
					+ SI_TABLE("turbo_node_info")+ " t2"
					+ " left join "+ SI_TABLE("turbo_sys_info")+ " t3 on t2.id = t3.node_id"
					+ "	 where (t1.node_id_creator = t2.id or t1.node_id_to = t2.id)"
					+ "	   and (t1.node_id_creator = ? or t1.node_id_to = ? ) and t2.islocal ='0'"
					+" group by t2.id,t2.node_name";
			return CM.getDao().list("获取节点进行数据交换的节点列表", sql,
					new NodeInfoRowWapper(),
					new Object[] { nodeId, nodeId });
		} catch (DaoException e) {
			throw new DaoException("获取与本节点进行数据交换的节点列表失败！", e);
		}
	}
	
	public boolean isSyncUrlExist(String syncUrl) throws DaoException {
		String sql = "select count(1) from "+ SI_TABLE("turbo_node_info")+" where upper(INSTALL_URL)=?";
		Integer num = null;
		try {
			num = CM.getDao().queryForInt("验证同步地址是否已经被其他节点占用", sql, new Object[]{syncUrl.toUpperCase()});
		} catch (DaoException e) {
			throw new DaoException("验证同步地址是否已经被其他节点占用失败！", e);
		}
		return num!=null&&num!=0;
	}

	public boolean nodeExitsByRegionCode(String checkNodeExitsByRegionCode) throws DaoException {
		if(StringUtils.hasText(checkNodeExitsByRegionCode)){
			String sql = "select count(*) from "+ SI_TABLE("turbo_node_info");
			WhereCondition whereCondition = new WhereCondition();
			whereCondition.where().like("node_code", LikeValue.afterLike(checkNodeExitsByRegionCode));
			try {
				Integer num = CM.getDao().queryForInt("根据行政区编码验证节点是否存在", sql, whereCondition, new Object[]{});
				return num!=null&&num!=0;
			} catch (DaoException e) {
				throw new DaoException("根据行政区编码验证节点是否存在失败！", e);
			}
		}
		return false;
	}
	
	/**
	 * 通过节点id返回交换关系节点列表
	 * @param nodeId
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getAllExchNodeListByNodeId(String nodeId) throws DaoException {
		try {
			final String sql = "select distinct t2.*"
					+ " from "+ SI_TABLE("turbo_exch_rel")+ " t1, "+ SI_TABLE("turbo_node_info")+ " t2"
					+ "	 where (t1.node_id_creator = t2.id or t1.node_id_to = t2.id)"
					+ "	   and (t1.node_id_creator = ? or t1.node_id_to = ? ) ";
			return CM.getDao().list("通过节点id返回交换关系节点列表", sql, new NodeInfoRowWapper(),
					new Object[] {nodeId,nodeId});
		} catch (DaoException e) {
			throw new DaoException("通过节点id返回交换关系节点列表失败！", e);
		}
	}
	/**
	 * 通过网络类型返回节点列表
	 * @param netType
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getListByNetType(String netType)throws DaoException {
		try {
			final String sql = "select * from " + SI_TABLE("turbo_node_info")+" where net_type = ? and status='1'";
			return CM.getDao().list("通过网络类型返回节点列表", sql, new NodeInfoRowWapper(),
					new Object[] {netType});
		} catch (DaoException e) {
			throw new DaoException("通过网络类型返回节点列表失败！", e);
		}
	}
	/**
	 * 获取本地虚拟管理节点
	 * @param netType
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getLocalDummyNode(String netType) throws DaoException {
		try {
			final String sql = "select * from " + SI_TABLE("TURBO_NODE_INFO t")
										+"  where subStr(node_code, 0, 6) =(select subStr(node_code, 0, 6)  from " + SI_TABLE("TURBO_NODE_INFO") + " where islocal = '1')"
										+" 	   and is_mgr_node = '1'"
										+" 	   and net_type = ? and status='1'";
			return CM.getDao().get("通过节点id返回交换关系节点列表", sql, new NodeInfoRowWapper(),new Object[] {netType});
		} catch (DaoException e) {
			throw new DaoException("通过节点id返回交换关系节点列表失败！", e);
		}
	}
	
	/**
	 * 获得根节点
	 * @param mwrNodePid　水利部pid
	 * @param netType　网络类型
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getRootNodeInfoByPidAndNetType(String mwrNodePid,String netType) throws DaoException {
		try {
			final String sql = "select * from " + SI_TABLE("turbo_node_info")+" where pid = ? and net_type = ? and status='1'";
			return CM.getDao().get("获得根节点", sql, new NodeInfoRowWapper(),
					new Object[] {mwrNodePid,netType});
		} catch (DaoException e) {
			throw new DaoException("通过节点id返回交换关系节点列表失败！", e);
		}
	}
	/**
	 * 通过节点编码获得节点
	 * @param nodeCode
	 * @return
	 * @throws DaoException
	 */
	public NodeInfo getNodeByNodeCode(String nodeCode) throws DaoException {
		try {
			final String sql = "select * from " + SI_TABLE("turbo_node_info")+" where node_code = ? ";
			return CM.getDao().get("通过节点编码获得节点", sql, new NodeInfoRowWapper(),
					new Object[] {nodeCode});
		} catch (DaoException e) {
			throw new DaoException("通过节点编码获得节点失败！", e);
		}
	}
	/**
	 * 根据节点编码获取节点列表
	 * @param nodeCodes
	 * @return
	 * @throws DaoException
	 */
	public List<NodeInfo> getNodeListByNodeCode(String[] nodeCodes) throws DaoException {
		try {
			if(nodeCodes!=null&&nodeCodes.length!=0){
				final String sql = "select * from " + SI_TABLE("turbo_node_info");
				WhereCondition condition = new WhereCondition();
				condition.where().in("node_code", nodeCodes);
				return CM.getDao().listModule("通过节点编码获得节点", sql, NodeInfo.class,
						condition);
			}else{
				return null;
			}
		} catch (DaoException e) {
			throw new DaoException("通过节点编码获得节点失败！", e);
		}
	}
}
